#include "esp8266.h"
#include "stm32f1xx_hal.h"
#include "string.h"
#include "json/cJSON.h"
#include "stdio.h"
#include "global/global.h"

#define CLIENT_ID "cli_nF7kbXlHNp"

//测试
const char *AT = "AT\r\n";

//设置station模式，可以连接热点
const char *AT_CWMODE = "AT+CWMODE=1\r\n";

//查询 Wi-Fi 状态和 Wi-Fi 信息
const char *AT_CWSTATE_R = "AT+CWSTATE?\r\n";
//连接热点
const char *AT_CWJAP = "AT+CWJAP=\"qsqya\",\"85123456\"\r\n";

//端口MQTT连接
const char *AT_MQTTCLEAN = "AT+MQTTCLEAN=0\r\n";

//配置 MQTT 用户属性,client_id先不写，username和password使用填生成的参数
const char *AT_MQTTUSERCFG = "AT+MQTTUSERCFG=0,1,\"cli_nF7kbXlHNp\",\"unm_nF7kbmTEWj\",\"pwd_nF7kbD3fpV\",0,0,\"\"\r\n";

//设置 MQTT 客户端 ID,ClientId填生成的参数，注意要在每个逗号前加分隔符"\"
const char *AT_MQTTCLIENTID = "AT+MQTTCLIENTID=0,\"ixikxvYd30o.light|securemode=2\\,signmethod=hmacsha256\\,timestamp=1687599441999|\"\r\n";

//连接 MQTT Broker,连接域名填上面生成的，注意要去掉端口号1883，因为后面已经设置了
const char *AT_MQTTCONN = "AT+MQTTCONN=0,\"192.168.3.2\",1883,1\r\n";

//查询 ESP8266设备已连接的 MQTT broker
const char *AT_MQTTCONN_R = "AT+MQTTCONN?\r\n";

//订阅指定 MQTT topic 	
//const char *AT_MQTTSUB = "AT+MQTTSUB=0,\"ESP8266/EMQX\",0\r\n";
const char *AT_MQTTSUB1 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/startEvent/post_reply\",0\r\n";
const char *AT_MQTTSUB2 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/property/post_reply\",0\r\n";
const char *AT_MQTTSUB3 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/property/set\",0\r\n";
const char *AT_MQTTSUB4 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/setRate\",0\r\n";
const char *AT_MQTTSUB5 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/openLight\",0\r\n";
const char *AT_MQTTSUB6 = "AT+MQTTSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/closeLight\",0\r\n";
//取消订阅
const char *AT_MQTTUNSUB = "AT+MQTTUNSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/runTimeEvent/post_reply\"\r\n";
const char *AT_MQTTUNSUB1 = "AT+MQTTUNSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/property/post_reply\"\r\n";
const char *AT_MQTTUNSUB3 = "AT+MQTTUNSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/property/set\"\r\n";
const char *AT_MQTTUNSUB4 = "AT+MQTTUNSUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/setRate\"\r\n";

//通过 topic 发布 MQTT消息
//{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"startEvent\\\"\\,\\\"params\\\":{\\\"clientId\\\":\\\"%s\\\"}}
const char *AT_MQTTPUB_startEvent = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/startEvent/post\",\"{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"startEvent\\\"\\,\\\"params\\\":{\\\"clientId\\\":\\\"%s\\\"}}\",0,0\r\n";
const char *AT_MQTTPUB_startEvent2 = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/startEvent/post\",\"11\",0,0\r\n";
//{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"property_post\\\"\\,\\\"params\\\":{\\\"light\\\":%d\\,\\\"clientId\\\":\\\"%s\\\"}}
const char *AT_MQTTPUB_2 = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/event/property/post\",\"{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"property_post\\\"\\,\\\"params\\\":{\\\"light\\\":%d\\,\\\"clientId\\\":\\\"%s\\\"}}\",0,0\r\n";
//{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"setRate\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}
const char *AT_MQTTPUB_setRate = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/setRate_reply\",\"{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"setRate\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}\",0,0\r\n";
//{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"openLight\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}
const char *AT_MQTTPUB_openLight = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/setRate_reply\",\"{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"openLight\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}\",0,0\r\n";
//{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"closeLight\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}
const char *AT_MQTTPUB_closeLight = "AT+MQTTPUB=0,\"/sys/proriEmYsU9iq/Light1/thing/service/setRate_reply\",\"{\\\"id\\\":\\\"%s\\\"\\,\\\"method\\\":\\\"closeLight\\\"\\,\\\"code\\\":0\\,\\\"data\\\":{\\\"clientId\\\":\\\"%s\\\"}}\",0,0\r\n";




extern UART_HandleTypeDef huart2;
uint8_t isIdle = 0;
#define RX_SIZE 200
uint8_t rxData[RX_SIZE] = {0};

#define CMD_SIZE 300
char cmd[CMD_SIZE] = {0};


void esp8266_init(void)
{
	__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);
	HAL_UART_Receive_DMA(&huart2,(uint8_t*)rxData,RX_SIZE);
	uint8_t ret = -1;
	ret = esp8266_cmd(AT,"OK",100);
	ret = esp8266_cmd(AT_CWSTATE_R,"OK",100);
	if(!(ret == 0 &&  esp8266_checkCode("+CWSTATE:2,\"qsqya\"") == 0))
	{
		ret = esp8266_cmd(AT_CWMODE,"OK",100);
		ret = esp8266_cmd(AT_CWJAP,"OK",1000);
	}
	//断开连接
//	ret = esp8266_cmd(AT_MQTTCLEAN,"OK",10000);
	ret = esp8266_cmd(AT_MQTTCONN_R,"OK",10000);
	if(!(ret == 0 &&  (esp8266_checkCode("+MQTTCONN:0,4") == 0 || esp8266_checkCode("+MQTTCONN:0,6") == 0)))
	{
		ret = esp8266_cmd(AT_MQTTUSERCFG,"OK",10000);
//		ret = esp8266_cmd(AT_MQTTCLIENTID,"OK",10000);
		ret = esp8266_cmd(AT_MQTTCONN,"OK",10000);
	}
	ret = esp8266_cmd(AT_MQTTSUB1,"OK",10000);
	ret = esp8266_cmd(AT_MQTTSUB2,"OK",10000);
	ret = esp8266_cmd(AT_MQTTSUB3,"OK",10000);
	ret = esp8266_cmd(AT_MQTTSUB4,"OK",10000);
	ret = esp8266_cmd(AT_MQTTSUB5,"OK",10000);
	ret = esp8266_cmd(AT_MQTTSUB6,"OK",10000);
	ret = esp8266_cmd(AT_MQTTCONN_R,"OK",10000);
	ret = esp8266_cmd(AT_MQTTCONN_R,"OK",10000);
	
	esp8266_startEvent();
}


uint8_t esp8266_cmd(const char* cmd,char* check,uint16_t delay)
{
	memset(rxData,0,RX_SIZE);
	HAL_UART_Transmit_DMA(&huart2,(uint8_t*)cmd,strlen(cmd));
	isIdle = 0;
	while(1){
		delay--;
		HAL_Delay(1);
		if(delay == 0)
			return 1;
		if(isIdle == 1){
			break;
		}
	}
	HAL_Delay(100);
	if(esp8266_checkCode(check) != 0) return 2;
//	memset(rxData,0,RX_SIZE);
	return 0;
}




void esp8266_setRateService()
{
	char id[64] ={0};
	char method[32] ={0};
	char clientId[64] ={0};
	
	char *startPtr = strstr((const char*)rxData,"{");
	cJSON *json = cJSON_ParseWithLength(startPtr,strlen(startPtr));
	cJSON *curJson = json->child;
	char *jid = curJson->valuestring;
	memcpy(id,jid,strlen(jid));
	curJson = curJson->next;
	char *jmethod = curJson->valuestring;
	memcpy(method,jmethod,strlen(jmethod));
	curJson = curJson->next;
	//
		cJSON *curJson1 = curJson->child;
		char *jclientId = curJson1->valuestring;
		memcpy(clientId,jclientId,strlen(jclientId));
		curJson1 = curJson1->next;
		rate = curJson1->valueint;
	//
	
	
	memset(cmd, 0, CMD_SIZE);
	sprintf(cmd, AT_MQTTPUB_setRate, id, CLIENT_ID);
	HAL_UART_Transmit_DMA(&huart2, (uint8_t*)cmd, strlen(cmd));
	
	cJSON_Delete(json);
}

void esp8266_openLightService()
{
	char id[64] ={0};
	char method[32] ={0};
	char clientId[64] ={0};
	
	char *startPtr = strstr((const char*)rxData,"{");
	cJSON *json = cJSON_ParseWithLength(startPtr,strlen(startPtr));
	cJSON *curJson = json->child;
	char *jid = curJson->valuestring;
	memcpy(id,jid,strlen(jid));
	curJson = curJson->next;
	char *jmethod = curJson->valuestring;
	memcpy(method,jmethod,strlen(jmethod));
	curJson = curJson->next;
	//
		cJSON *curJson1 = curJson->child;
		char *jclientId = curJson1->valuestring;
		memcpy(clientId,jclientId,strlen(jclientId));
	//
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
	
	memset(cmd, 0, CMD_SIZE);
	sprintf(cmd, AT_MQTTPUB_openLight, id, CLIENT_ID);
	HAL_UART_Transmit_DMA(&huart2, (uint8_t*)cmd, strlen(cmd));
	
	cJSON_Delete(json);
}

void esp8266_closeLightService()
{
	char id[64] ={0};
	char method[32] ={0};
	char clientId[64] ={0};
	
	char *startPtr = strstr((const char*)rxData,"{");
	cJSON *json = cJSON_ParseWithLength(startPtr,strlen(startPtr));
	cJSON *curJson = json->child;
	char *jid = curJson->valuestring;
	memcpy(id,jid,strlen(jid));
	curJson = curJson->next;
	char *jmethod = curJson->valuestring;
	memcpy(method,jmethod,strlen(jmethod));
	curJson = curJson->next;
	//
		cJSON *curJson1 = curJson->child;
		char *jclientId = curJson1->valuestring;
		memcpy(clientId,jclientId,strlen(jclientId));
	//
	
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
	
	memset(cmd, 0, CMD_SIZE);
	sprintf(cmd, AT_MQTTPUB_closeLight, id, CLIENT_ID);
	HAL_UART_Transmit_DMA(&huart2, (uint8_t*)cmd, strlen(cmd));
	
	cJSON_Delete(json);
}


void esp8266_idle_callback(void)
{
	HAL_UART_DMAStop(&huart2);
	isIdle = 1;
	//do something
	if(esp8266_checkCode("+MQTTSUBRECV") == 0){
		if(esp8266_checkCode("property_set") == 0){
			char *startPtr = strstr((const char*)rxData,"params")+8;
			cJSON *json = cJSON_ParseWithLength(startPtr,strlen(startPtr));
			char *name = json->child->string;
			int value = json->child->valueint;
			light = value;
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
			cJSON_Delete(json);
		}else if(esp8266_checkCode("setRate") == 0){
			esp8266_setRateService();
		}else if(esp8266_checkCode("openLight") == 0){
			esp8266_openLightService();
		}else if(esp8266_checkCode("closeLight") == 0){
			esp8266_closeLightService();
		}

		memset(rxData,0,RX_SIZE);
	}else if(esp8266_checkCode("AT+MQTTPUB") == 0){
		memset(rxData,0,RX_SIZE);
	}
	
	HAL_UART_Receive_DMA(&huart2,(uint8_t*)rxData,RX_SIZE);
}

uint8_t esp8266_checkCode(char *code)
{
	char* res = strstr((const char*)rxData,code);
	if(res == NULL) return 1;
	return 0;
}


char* esp8266_newId()
{
	static uint32_t flag = 0;//从服务器来
	//uuid生成
	static char id[64];
	memset(id,0,64);
	sprintf(id,"%s-%d",CLIENT_ID,flag++);
	return id;
}

void esp8266_createProperty()
{
//	static uint32_t flag = 0;//从服务器来
//	//uuid生成
//	char id[64];
//	sprintf(id,"%s-%d",CLIENT_ID,flag++);
	memset(cmd, 0, CMD_SIZE);
	sprintf(cmd, AT_MQTTPUB_2, esp8266_newId(), light, CLIENT_ID);
	HAL_UART_Transmit_DMA(&huart2, (uint8_t*)cmd, strlen(cmd));
}

void esp8266_startEvent()
{
	memset(cmd, 0, CMD_SIZE);
	sprintf(cmd, AT_MQTTPUB_startEvent, esp8266_newId(), CLIENT_ID);
	HAL_UART_Transmit_DMA(&huart2, (uint8_t*)cmd, strlen(cmd));
}



